﻿#include "scene_instance.h"
#include <algorithm>
#include "../share/log.h"
#include "../share/geometry.h"
#include "scene_manager.h"
#include "mapobj_manager.h"
#include "Player.h"
#include "../share/time_module.h"
#include "../share/MessageDef.h"
#include "SceneElementFileIndexTable.h"
#include "entity_define.h"
#include "MonsterTable.h"
#include "Fixed1024.h"
#include "PlayerDataStruct.inl"



bool CNearSelector::operator( ) ( CEntity* entity ) const
{
	if( NULL == entity )
	{
		return false;
	}
	if( ( ( 1 << entity->GetEntityType( ) ) & entity_type_ ) == 0 )
	{
		return false;
	}
	return ( entity->get_id( ) != player_.get_id( ) );
}

CSceneInstance::CSceneInstance( )
{
	tpl_id_ = 0;
	line_id_ = 0;
	vision_width_ = 0;
	vision_height_ = 0;
//	player_list_ = NULL;
//	entity_list_ = NULL;
	cell_size_ = 0;
	creature_die_count_ = 0;
	scene_state_ = 0;
	update_sec_ = 0;
	service_id_ = 0;
    instance_id_ = 0;
	start_time_ = 0;
    width_ = 0;
    height_ = 0;
    vision_cell_size_ = 0;
    vision_radius_height_ = 0;
    vision_radius_width_ = 0;
    script_ = main_city;
	last_logic_frame_ = 0;
	special_tick_ = 0;
	vision_limit_ = 0;
	main_scene_id_ = 0;
}

CSceneInstance::~CSceneInstance( )
{
/*
	if ( NULL != player_list_ )
	{
		delete[] player_list_;
		player_list_ = NULL;
	}
	if ( NULL != entity_list_ )
	{
		delete[] entity_list_;
		entity_list_ = NULL;
	}
*/
	scene_cell_mgr_.clear( );
	for( TCreatureSet::iterator iter = creatures_.begin( ); iter != creatures_.end( ); ++iter )
	{
		CMAPObjManager::GetInstance( ).DestoryObject( *iter );
	}
	creatures_.clear( );

	for( TCreatureSet::iterator iter = common_creatures_.begin( ); iter != common_creatures_.end( ); ++iter )
	{
		CMAPObjManager::GetInstance( ).DestoryObject( *iter );
	}
	common_creatures_.clear( );


	for( TRobotList::iterator iter = robot_list_.begin( ); iter != robot_list_.end( ); ++iter )
	{
		CMAPObjManager::GetInstance( ).DestoryObject( *iter );
	}
	robot_list_.clear( );

	for( TTimerMap::iterator iter = timers_.begin( ); iter != timers_.end( ); ++iter )
	{
		OBJ_ID_TYPE timer_id = iter->second;
		CMAPObjManager::GetInstance( ).DestoryObject( timer_id );
	}	
	timers_.clear( );

	for( TDespawnCreatureList::iterator iter = creature_destroy_list_.begin( ); iter != creature_destroy_list_.end( ); ++iter )
	{
		OBJ_ID_TYPE creature_obj_id = *iter;
		CMAPObjManager::GetInstance( ).DestoryObject( creature_obj_id );
	}

	creatures_key_id.clear();
	creatures_.clear();
	creature_destroy_list_.clear( );

	creature_special_list_.clear( );
}

CSceneCell* CSceneInstance::GetSceneCell( int32_t cell_index ) const
{
    return scene_cell_mgr_.GetSceneCell( cell_index );
}

void CSceneInstance::OnSceneCreate( )
{
	SceneConfigureInfo* tpl = SceneConfigureTable::GetInstance().GetScenceConfigureInfoById(tpl_id_);
	if (NULL == tpl)
	{
		LOG_ERROR("default", "tpl [%u] is not exits", tpl_id());
		return;
	}

	if (tpl_id_ < 20100)
	{
		return;
	}

	// 刚创建副本的时候要出生的怪物
	std::vector<SceneElement> create_monster;
	SceneElementFileIndexTable::GetInstance().GetSceneElementVectorById(tpl_id_, create_monster);
	for (std::vector<SceneElement>::const_iterator iter = create_monster.begin( ); iter != create_monster.end( ); ++iter )
	{
		Monster* monster =  CMAPObjManager::GetInstance().CreateObject< Monster >(OBJTYPE_CREATURE);
		if ( monster == NULL )
		{
			LOG_ERROR("default", "create creature err! type[%d]", iter->m_type);
			return;
		}
		
		monster->SetKey(iter->m_key);
		monster->SetNotEmpty();

		monster->SetSpawnPointX(iter->m_x_pos);
		monster->SetSpawnPointY(iter->m_y_pos);
		monster->SetSpawnPointZ(iter->m_z_pos);

		//monster->SetPosX(iter->m_x_pos);
		//monster->SetPosY(iter->m_y_pos);
		//monster->SetPosZ(iter->m_z_pos);
		::common::CVector3 position(iter->m_x_pos, iter->m_y_pos, iter->m_z_pos);
		monster->set_position(position);
		monster->set_instance_id(instance_id_);
		monster->set_spawn_point(position);

		monster->SetTypeId(iter->m_type_id);		//	类型id，具体内容需要查询其他表
		monster->SetObjectType((GameObjectType)(iter->m_type + GOT_PLAYER));
		monster->SetClientType((GameObjectType)(iter->m_type + GOT_PLAYER));
//		monster->SetSceneId(tpl_id_);

		if (GOT_MONSTER == monster->GetObjectType() ||
			GOT_RAND_MONSTER == monster->GetObjectType())
		{
			MonsterSetInfo* pMonster = MonsterTable::GetInstance().GetMonsterInfo(monster->GetTypeId());
			if (NULL == pMonster)
			{
				LOG_ERROR("default", "create monster err monster[%d]", monster->GetTypeId());
				continue;
			}
			
			monster->InitByTpl(pMonster);

			creatures_.insert(monster->get_id());
			creatures_key_id.insert(std::make_pair(iter->m_key, monster->get_id()));
		}
		else
		{
			common_creatures_.insert(monster->get_id());
		}

		AddEntityToAOI(*monster);
		BroadcastInvision(*monster);

		LOG_DEBUG("default", "monster[%d:%d] is create in position[%f,%f,%f]", monster->get_id(), monster->GetTypeId(), monster->position().x(), monster->position().y(), monster->position().z());

		//怪物出生事件
		//creature_born_event(*monster);
	}

	DumpPosition();
	Dump();
}



void CSceneInstance::OnSceneDestory( )
{
	for ( TCreatureSet::iterator iter = creatures_.begin( ); iter != creatures_.end( ); ++iter )
	{
		CMAPObjManager::GetInstance( ).DestoryObject( *iter );
	}
	creatures_.clear( );
	creatures_key_id.clear();

	for ( TCreatureSet::iterator iter = common_creatures_.begin( ); iter != common_creatures_.end( ); ++iter )
	{
		CMAPObjManager::GetInstance( ).DestoryObject( *iter );
	}
	common_creatures_.clear( );

	for( TTimerMap::iterator iter = timers_.begin( ); iter != timers_.end( ); ++iter )
	{
		CMAPObjManager::GetInstance( ).DestoryObject( iter->second );
	}
	timers_.clear( );

	for( int32_t i = 0; i < cell_size_; ++i )
	{
		SceneCellPlayerLoop(
			i,
			continue,
			{
				Player* player = node->parent( );
				if( player != NULL )
				{
					//CSceneManager::GetInstance( ).LeaveDungeon( *player );
				}
			}
		);	
	}
}

void CSceneInstance::OnPlayerEnter( Player& player )
{
	SSceneRoleData* role_data = GetSceneRoleData(player.GetPlayerId());
	if (NULL == role_data)
	{
		SSceneRoleData new_role_data;
		new_role_data.role_id = player.GetPlayerId();
		role_data_map_.insert(std::make_pair(player.GetPlayerId(), new_role_data));
	}
}

void CSceneInstance::OnPlayerConnect( Player& player )
{
	NotifyVision(player);
}

void CSceneInstance::OnSceneWin( )
{
// 	LOG_INFO( "default", "scene is win : %d %d %ld", tpl_id_, get_id( ), instance_id_ );
// 	logic_end_time_ = CUR_SEC;
// 	TriggerEvent( NULL, TRIGGER_EVENT_SCENE_WIN, 0 );
// 	CWorldLevelModule::GetInstance().OnInstanceWin(*this);
// 	CSceneScript& scene_script = CSceneManager::GetInstance( ).GetSceneScript( script_ );
// 	scene_script.OnSceneWin( *this );
// 	scene_state_ = SCENE_STATE_LOGIC_END;
// 	AddLogicEndBuff();
// 	StopAI( );
// 	CheckDestory( );
}

void CSceneInstance::OnSceneLose( int32_t code )
{
// 	LOG_INFO( "default", "scene is lose :%d %d %ld", tpl_id_, get_id( ), instance_id_ );
// 	logic_end_time_ = CUR_SEC;
// 	TriggerEvent( NULL, TRIGGER_EVENT_SCENE_LOSE, code );
// 	CSceneScript& scene_script = CSceneManager::GetInstance( ).GetSceneScript( script_ );
// 	scene_script.OnSceneLose( *this, code );
// 	scene_state_ = SCENE_STATE_LOGIC_END;
// 	AddLogicEndBuff();
//     StopAI( );
// 	CheckDestory( );
}

bool CSceneInstance::Setup( const SceneConfigureInfo& tpl )
{
	tpl_id_ = tpl.m_key;
	if ( tpl_id_ == 20000 )
	{
		script_ = main_city;
	}
	else if ( tpl_id_ == 20100)
	{
		script_ = wild;
	}
	start_time_ = CUR_SEC;

	
    vision_cell_size_ = 4;
    vision_radius_width_ = 1;
    vision_radius_height_ = 1;

    width_ = tpl.m_x_size;
    height_ = tpl.m_z_size;
// 	width_ = 64;
// 	height_ = 64;
	vision_width_ = width_ / vision_cell_size_;
	vision_height_ = height_ / vision_cell_size_;
	cell_size_ = vision_width_ * vision_height_;
	
	scene_cell_mgr_.Init( *this, cell_size_, vision_width_, vision_height_ );


// 	CSceneScript& script = CSceneManager::GetInstance( ).GetSceneScript( tpl.script( ) );
// 	if( script.Setup( *this, args ) == false )
// 	{
// 		return false;
// 	}
	return true;
}

void CSceneInstance::LinkEntity( CEntity& entity )
{
	int32_t cell_index = GetCellIndex( entity.position( ) );
	if ( cell_index < 0 || cell_index >= cell_size_ )
	{
		LOG_WARN( "default", "entity %d link invalid index[ %d ] pos[ x: %f z : %f ] ", entity.get_id( ), cell_index, 
			
			entity.position( ).x( ), entity.position( ).z( ) );
		return;
	}
    CSceneCell* scene_cell = scene_cell_mgr_.GetSceneCell( cell_index );
    if( scene_cell == NULL )
    {
        LOG_ERROR( "default", "scene tpl %d cann get cell_index %d, pos %f:%f", tpl_id( ), cell_index, entity.position( ).x( ),
                entity.position( ).z( ) );
        return;
    }

	LOG_INFO( "default" ,"entity %d link cell %d", entity.get_id( ), cell_index );

    entity.entity_link( ).LinkAfter( scene_cell->entity_list( ) );
    if ( entity.GetEntityType( ) == OBJTYPE_PLAYER )
    {
        Player& player = ( Player& )( entity );
        player.player_link( ).LinkAfter( scene_cell->player_list( ) );
    }
}

void CSceneInstance::UnlinkEntity( CEntity& entity )
{
	entity.entity_link( ).Unlink( );
	if( entity.GetEntityType( ) == OBJTYPE_PLAYER )
	{
		Player& player = ( Player& )( entity );
		player.player_link( ).Unlink( );
	}
}

int32_t CSceneInstance::GetCellIndex( const ::common::CVector3& position ) const
{
	int32_t w =  position.x( ) / vision_cell_size_;
	int32_t h =  position.z( ) / vision_cell_size_;
	return w + h * vision_width_;
}

void CSceneInstance::BroadcastCellViewMessage( int32_t cell_index, uint32_t msg_id, Json::Value& msg, int32_t exclude_role_id, CEntity* entity )
{
	::common::CRect rect;
	if ( GetRectInRadius( cell_index, vision_radius_width_, vision_radius_height_, rect ) == false )
	{
		LOG_WARN( "default", "invalid cell in map[%d]", cell_index, tpl_id_ );
		return;
	}

	// 是玩家 广播给他附件的玩家
	Player* player = nullptr;
	if (entity != nullptr && entity->GetEntityType() == OBJTYPE_PLAYER) {
		player = dynamic_cast<Player*>(entity);

		//if (player != nullptr) {
		//	SendMsg2Broadcast(msg_id, msg, player->vision_link().GetBroadList());
		//	return;
		//}
	}


	T_BROADCAST_PLAYER_TYPE& broadcast_list = broadcast_list_;
	broadcast_list.clear( );
	for ( int32_t x = rect.xmin( ); x <= rect.xmax( ); ++x )
	{
		for ( int32_t z = rect.zmin( ); z <= rect.zmax( ); ++z )
		{
			int32_t index = x + z * vision_width_;
			CSceneCell* scene_cell = scene_cell_mgr_.GetSceneCell(index);			
			if (scene_cell == NULL) continue;										
			::common::CListLink< Player >& player_list = scene_cell->player_list();	
			for (::common::CListLink< Player >* node = player_list.next_node(); node != NULL; node = node->next_node()) 
			{ 
				Player* watcher = node->parent();
				if (NULL == watcher) continue;

				if (watcher->GetPlayerId() != exclude_role_id)
				{
					// 						if( msg_id == ID_CORE_ENTITY_IN_VISION && entity != NULL )
					// 						{
					// 							int32_t rtn = SceneAddVision( *watcher, *entity );
					// 							if( rtn != common::SUCCEED ) continue;
					// 						}
					// 						else if( msg_id == ID_CORE_ENTITY_OUT_VISION && entity != NULL )
					// 						{
					// 							int32_t rtn = SceneRemoveVision( *watcher, *entity );
					// 							if( rtn != common::SUCCEED) continue;
					// 						}
					// 						else if( entity != NULL )
					// 						{
					// 							int32_t rtn = SceneSendMsg( *watcher, *entity, msg_id, msg );
					// 							if( rtn != common::SUCCEED)
					// 							{ 
					// 								LOG_DEBUG( "default", "watcher %d %d throw msg id %d entity %d", watcher->GetAccountID( ), 
					// 									watcher->GetPlayerId( ),  msg_id, entity->get_id( ) );
					// 								continue;
					// 							}
					// 						}
					// 怪要发给所有人
					if (player == nullptr)
					{
						broadcast_list.push_back(watcher);
						continue;
					}
					// 谁能看见我就给谁发
					if (player != nullptr && watcher->vision_link().FindFromBroadList(player->GetPlayerId())) {
						broadcast_list.push_back(watcher);
					}

					if (msg_id == delete_walk_object && player) {
						SceneRemoveVision(*watcher, *player);
					}
				}
			}
// 			SceneCellPlayerLoop( index, continue,
// 				{
// 					
// 				}
//			);
		}
	}
	SendMsg2Broadcast( msg_id, msg, broadcast_list);
}

void CSceneInstance::BroadcastViewMessage(CEntity& entity, uint32_t msg_id, Json::Value& msg, int32_t exclude_role_id )
{
	int32_t cell_index = GetCellIndex( entity.position( ) );
	if ( cell_index < 0 || cell_index >= cell_size_ )
	{
		LOG_WARN( "default", "invalid position[%f,%f] of entity", entity.position( ).x( ), entity.position( ).z( ) );
		return;
	}

	BroadcastCellViewMessage( cell_index, msg_id, msg, exclude_role_id, &entity );
	return;
}

void CSceneInstance::AddEntityToAOI( CEntity& entity )
{
	LinkEntity( entity );
}

void CSceneInstance::RemoveEntityFromAOI( CEntity& entity )
{
	UnlinkEntity( entity );
}

void CSceneInstance::MoveEntity(CEntity& entity, const ::common::CVector3& dst_pos )
{
    //TODO,判断这个坐标是否在地图内;
    if( dst_pos.x( ) < 0 || dst_pos.x( ) > width_ ||
        dst_pos.z( ) < 0 || dst_pos.z( ) > height_ )
    {
        LOG_ERROR( "default", "<MOVE> to invalid position : %f %f", dst_pos.x( ), dst_pos.z( ) );
        return;
    }
	::common::CVector3 old_pos = entity.position( );
	entity.set_position( dst_pos );
	OnEntityMove( entity, old_pos );

// 	if( ::common::WithinDistanceEx(old_pos, dst_pos, 0.0001f) == false )
// 	{
// 		entity_move_event( entity );
// 	}
}

void CSceneInstance::OnEntityMove( CEntity& entity, const ::common::CVector3& old_pos )
{
	int32_t new_cell_index = GetCellIndex( entity.position( ) );
	int32_t old_cell_index = GetCellIndex( old_pos );
	if ( new_cell_index < 0 || new_cell_index >= cell_size_ || old_cell_index < 0 || old_cell_index >= cell_size_ )
	{
		LOG_ERROR( "default", "entity %d error cell index : %d->%d", entity.get_id( ), old_cell_index, new_cell_index );
		return;
	}
	::common::CRect old_rect;
	GetRectInRadius( old_cell_index, vision_radius_width_, vision_radius_height_, old_rect );
	::common::CRect new_rect;
	GetRectInRadius( new_cell_index, vision_radius_width_, vision_radius_height_, new_rect );
	
	Player* playerptr = nullptr;
	if (entity.GetEntityType() == OBJTYPE_PLAYER) {
		playerptr = dynamic_cast<Player*>(&entity);
	}
	else {
		playerptr = nullptr;
	}
	
	if ( new_cell_index != old_cell_index )
	{
		//格子发生了变化
		//1.通知其他实体，这个角色离开视野;
		//
		LinkEntity( entity );
		{
			Json::Value notify;
			notify["msgid"] = delete_walk_object;
			Json::Value _arrayObj;
			Json::Value key = entity.GetKey();
			_arrayObj.append(key);
			notify["dl"] = _arrayObj;
			T_BROADCAST_PLAYER_TYPE& broadcast_list = broadcast_list_;
			broadcast_list.clear( );
			
			for ( int32_t x = old_rect.xmin( ); x <= old_rect.xmax( ); ++x )
			{
				for ( int32_t z = old_rect.zmin( ); z <= old_rect.zmax( ); ++z )
				{
					//在老格子，但是不在新格子中的;
					int32_t index = x + z * vision_width_;
					if ( new_rect.IsContain( x, z ) == false )
					{
						CSceneCell* scene_cell = scene_cell_mgr_.GetSceneCell(index);			
						if (scene_cell == NULL) continue;
						::common::CListLink< Player >& player_list = scene_cell->player_list();	
						for (::common::CListLink< Player >* node = player_list.next_node(); node != NULL; node = node->next_node()) 
						{ 
							Player* watcher = node->parent();
							if (NULL == watcher) continue;

							SceneRemoveVision(*watcher, entity);
							// 谁能看见我就给谁发
							if (playerptr != nullptr && watcher->vision_link().FindFromBroadList(playerptr->GetPlayerId())) {
								broadcast_list.push_back(watcher);
								continue;
							}

							if (playerptr == nullptr) {
								broadcast_list.push_back(watcher);
								continue;
							}
						}
// 						SceneCellPlayerLoop( index, continue,
// 							{
// 								Player* watcher = node->parent( );
// 								if( NULL == watcher ) continue;
// 								SceneRemoveVision( *watcher, entity );
// 								broadcast_list.push_back( watcher );
// 							}
// 						);
					}
				}
			}
			//if (playerptr == nullptr) {
				SendMsg2Broadcast(delete_walk_object, notify, broadcast_list);
			//}
			//else {
			//	SendMsg2Broadcast(delete_walk_object, notify, playerptr->vision_link().GetBroadList());
			//}
		}

		//2.通知其他角色，有实体进入视野;
		{
			Json::Value notify;
			notify["msgid"] = add_walk_object;

			Json::Value _arrayObj;
			Json::Value _info;
			_arrayObj.clear();
			entity.SerialToJson(_info);
			_arrayObj.append(_info);
			notify["al"] = _arrayObj;
			T_BROADCAST_PLAYER_TYPE& broadcast_list = broadcast_list_;
			broadcast_list.clear( );
			for ( int32_t x = new_rect.xmin( ); x <= new_rect.xmax( ); ++x )
			{
				for ( int32_t z = new_rect.zmin( ); z <= new_rect.zmax( ); ++z )
				{
					//在新格子，但是不在老格子中;
					int32_t index = x + z * vision_width_;
					if ( old_rect.IsContain( x, z ) == false )
					{
						//通知其他玩家有玩家进入视野;
						CSceneCell* scene_cell = scene_cell_mgr_.GetSceneCell(index);			
						if (scene_cell == NULL) continue;
						::common::CListLink< Player >& player_list = scene_cell->player_list();
						for (::common::CListLink< Player >* node = player_list.next_node(); node != NULL; node = node->next_node())
						{
							Player* watcher = node->parent();
							if (NULL == watcher) continue;
							if (watcher->get_id() == entity.get_id()) continue;
							int32_t rtn = SceneAddVision(*watcher, entity);
							if (rtn != common::SUCCEED && playerptr != nullptr) continue;
							broadcast_list.push_back(watcher);
							
							//if (playerptr == nullptr) {
							
								//continue;
							//}

							//if (playerptr != nullptr && watcher->vision_link().FindFromBroadList(playerptr->GetPlayerId())) {
							//	broadcast_list.push_back(watcher);
							//	continue;
							//}
						}
// 						SceneCellPlayerLoop( index, continue, 
// 							{
// 								Player* watcher = node->parent( );
// 								if( NULL == watcher ) continue;
// 								if ( watcher->get_id() == entity.get_id() ) continue;
// 								int32_t rtn = SceneAddVision( *watcher, entity );
// 								if( rtn != common::SUCCEED ) continue;
// 								broadcast_list.push_back( watcher );
// 							}
// 						);
					}
				}
			}
			
				SendMsg2Broadcast(add_walk_object, notify, broadcast_list);
		}

		if( entity.GetEntityType() == OBJTYPE_PLAYER )
		{
			// 哪些人离开了我的视野
			Player& player = ( Player& )( entity );
			//3.通知这个角色，哪些实体离开它的视野;
			Json::Value outnotify;
			outnotify["msgid"] = delete_walk_object;
			Json::Value _arrayObj;
			for ( int32_t x = old_rect.xmin( ); x <= old_rect.xmax( ); ++x )
			{
				for ( int32_t z = old_rect.zmin( ); z <= old_rect.zmax( ); ++z )
				{
					//在老格子，但是不在新格子中的;
					if ( new_rect.IsContain( x, z ) == false )
					{
						int32_t index = x + z * vision_width_;
            			CSceneCell* scene_cell = scene_cell_mgr_.GetSceneCell( index );
            			if( scene_cell == NULL ) continue;	

						::common::CListLink< CEntity >& entity_list = scene_cell->entity_list( );
						for( ::common::CListLink< CEntity >* node = entity_list.next_node( ); node != NULL; node = node->next_node( ) )
						{
							CEntity* entity = node->parent( );
							if( entity != NULL )
							{
								SceneRemoveVision( player, *entity );
								Json::Value key = entity->GetKey();
								_arrayObj.append(key);
							}
						}
					}	
				}
			}
			if(_arrayObj.size( ) >  0 )
			{
				outnotify["dl"] = _arrayObj;
				std::string sendstr = JsonWriter(outnotify);
				player.SendToClient(&sendstr, delete_walk_object);
			}
			// 哪些人进入我的视野
			Json::Value innotify;
			innotify["msgid"] = add_walk_object;
			Json::Value inarrayObj;
			inarrayObj.clear();
			
			int32_t notify_num = 0;
			int32_t all_notify_num = 0;
			int32_t send_msg_num = 0;
			for ( int32_t x = new_rect.xmin( ); x <= new_rect.xmax( ); ++x )
			{
				for ( int32_t z = new_rect.zmin( ); z <= new_rect.zmax( ); ++z )
				{
					//在新格子，但是不在老格子中;
					int32_t index = x + z * vision_width_;
					
				//	if ( old_rect.IsContain( x, z ) == false )
					if ( old_rect.IsContain( x, z ) == true ) continue;

					SceneCellEntityLoop( index, continue,
						{
							CEntity* entity = node->parent( );
							if ( entity == NULL ) continue;
							if ( player.get_id() == entity->get_id() ) continue;
							int32_t rtn  = SceneAddVision( player, *entity );
							if( rtn != common::SUCCEED )  continue;

							Json::Value _info;
							entity->SerialToJson(_info);
							inarrayObj.append(_info);

							notify_num++;
							all_notify_num++;
							if( notify_num > 50 )
							{
								send_msg_num++;
								innotify["al"] = inarrayObj;
								std::string sendstr = JsonWriter(innotify);
								player.SendToClient(&sendstr, add_walk_object);
								notify_num = 0;
								inarrayObj.clear();
								innotify.clear();
							}
						}
					);
				}
			}



			if(inarrayObj.size() > 0 )
			{
				send_msg_num++;
				innotify["al"] = inarrayObj;
				std::string sendstr = JsonWriter(innotify);
				player.SendToClient(&sendstr, add_walk_object);
			}

			if( send_msg_num > 1 )
			{
				LOG_INFO( "default", "player %d notify invision send msg count %d all_notify %d", 
					player.GetPlayerId( ), send_msg_num, all_notify_num );
			}

		}
	}
}

bool CSceneInstance::GetRectInRadius( int32_t cell_index, int32_t radius_x, int32_t radius_z, ::common::CRect& rect ) const
{
	if ( vision_width_ <= 0 )
	{
		return false;
	}
	int32_t x = cell_index % vision_width_;
	int32_t z = cell_index / vision_width_;

	int32_t xmin = x - radius_x;
	rect.set_xmin( xmin < 0 ? 0 : xmin );

	int32_t xmax = x + radius_x;
	rect.set_xmax( xmax >= vision_width_ ? vision_width_ - 1 : xmax );

	int32_t zmin = z - radius_z;
	rect.set_zmin( zmin < 0 ? 0 : zmin );

	int32_t zmax = z + radius_z;
	rect.set_zmax( zmax >= vision_height_ ? vision_height_ - 1 : zmax );
	return true;
}

// CPathNode* CSceneInstance::GetPathNode( int32_t x, int32_t z, PBEntityLayer layer )
// {
// 	int32_t w =  x / vision_cell_size_;
// 	int32_t h =  z / vision_cell_size_;
// 	int32_t index = w + h * vision_width_;
// 
// 	TPathNodeMap::iterator iter = path_nodes_.find( index );
// 	if ( iter != path_nodes_.end( ) )
// 	{
// 		return iter->second;
// 	}
// 	else
// 	{
// 		CPathNode* node = CPathNodePool::GetInstance( ).Create( );
// 		node->set_x( x );
// 		node->set_z( z );
// 		if ( IsBlock( x, z, layer ) == true )
// 		{
// 			node->set_state( CPathNode::NODE_STATE_BLOCKED );
// 		}
// 		path_nodes_.insert( TPathNodeMap::value_type( index, node ) );
// 		return node;
// 	}
// }

bool CSceneInstance::IsBlock( const ::common::CVector3& position ) const
{
	return false;
	//return IsBlock( position.x( ), position.z( ), layer );
}

bool CSceneInstance::IsBlock( int32_t x, int32_t z ) const
{
// 	SDynamicBlock s_dynamic_block(x, z, layer);
// 	TDynamicBlockCountMap::const_iterator it = dynamic_block_count_map_.find(s_dynamic_block);
// 	if (it != dynamic_block_count_map_.end())
// 	{
// 		return true;
// 	}
// 
// 	const CSceneTpl* tpl = CTPLManager::GetInstance( ).GetSceneTpl( tpl_id_ );
// 	if ( NULL == tpl )
// 	{
// 		return true;
// 	}
// 	return tpl->IsBlock( x, z, layer );
	return false;
}


bool CSceneInstance::GroupSpawnCreatureEntity( int32_t group_id )
{
// 	const CSceneTpl* tpl = CTPLManager::GetInstance( ).GetSceneTpl( tpl_id_ );
// 	if( NULL == tpl )
// 	{
// 		LOG_ERROR( "default", "null == tpl" );
// 		return false;
// 	}
// 	for ( CSceneTpl::TCreatorMap::const_iterator iter = tpl->creators_.begin( ); iter != tpl->creators_.end( ); ++iter )
// 	{
// 		const CCreatureCreator& creator = iter->second;
// 		if( creator.group_id( ) == group_id )
// 		{
// 			SpawnCreatureEntity( creator );
// 		}
// 	}
	return true;
}
/*
CCreature* CSceneInstance::SpawnCreatureEntity( int32_t creator_id, int32_t level )
{
	const CSceneTpl* tpl = CTPLManager::GetInstance( ).GetSceneTpl( tpl_id_ );
	if( NULL == tpl )
	{
		LOG_ERROR( "default", "null == tpl" );
		return false;
	}
	for ( CSceneTpl::TCreatorMap::const_iterator iter = tpl->creators_.begin( ); iter != tpl->creators_.end( ); ++iter )
	{
		const CCreatureCreator& creator = iter->second;
		if( creator.creator_id( ) == creator_id )
		{
			return SpawnCreatureEntity( creator, level );
		}
	}
	return NULL;
}

CCreature* CSceneInstance::SpawnCreatureEntity( const CCreatureCreator& creator, int32_t level )
{
	if( IsBlock( creator.born_position( ), ( PBEntityLayer )creator.layer( ) ) == true )
	{
		LOG_ERROR( "default", "creature is in block : %d %d %d", tpl_id_, creator.creator_id( ), creator.tpl_id( ) );
		return NULL;
	}
    CCreature* creature = CMAPObjManager::GetInstance( ).CreateObject< CCreature >( OBJTYPE_CREATURE );
   	if ( NULL == creature )
   	{
       	LOG_ERROR( "default", "create creature failed" );
		return NULL;
    }
	const PBCreatureTpl* tpl = CTPLManager::GetInstance( ).GetCreatureTpl( creator.tpl_id( ) );
	if ( NULL == tpl )
	{
		LOG_ERROR( "default", "creature tpl is null : %d %d %d", tpl_id_, creator.creator_id( ), creator.tpl_id( ) );
		CMAPObjManager::GetInstance( ).DestoryObject( creature->get_id( ) );
		return NULL;
	}
	int32_t fix_lv = creator.fix_lv( ) == 0 ? level_fix_ : creator.fix_lv( );
	if ( level < 0 ) {
		level = tpl->level( ) + fix_lv;
	}
	if( creature->LoadTplData( *tpl, level )  == false )
	{
		LOG_ERROR( "default", "load tpl data failed : %d %d %d", tpl_id_, creator.creator_id( ), creator.tpl_id( ) );
		CMAPObjManager::GetInstance( ).DestoryObject( creature->get_id( ) );
		return NULL;
	}
	creature->set_creator_id( creator.creator_id( ) );
	creature->set_born_position( creator.born_position( ) );
	creature->set_position( creator.born_position( ) );
	creature->set_angle( creator.angle( ) );
	creature->set_layer( ( PBEntityLayer )creator.layer( ) );
	creature->set_group_id( creator.group_id( ) );
	creature->set_revive_time( creator.revive_time( ) );
	creature->set_wild_boss_revive_time( creator.wild_boss_revive_time( ) );
	creature->set_owner_id( creator.owner_id( ) );
   	creature->set_instance_id( instance_id_ );
   	creature->set_droper_id( creator.droper_id( ) );
    creature->set_camp_id( creator.camp_id( ) );
    if( creator.life_time( ) != 0 )
    {
        creature->set_life_time( CUR_MS + creator.life_time( ) * 1000 );
    }

	if( ( creature->HasAI( ) == true ) || creature->creature_type( ) == CREATURE_TYPE_TOTEM ||
		creature->creature_type() == CREATURE_TYPE_MARCH_NPC ||creature->life_time() != 0 )
	{
   		creatures_.insert( creature->get_id( ) );
	}
	else
	{
		common_creatures_.insert( creature->get_id( ) );
	}

	AddEntityToAOI( *creature );
	BroadcastInvision( *creature );

   	LOG_DEBUG( "default", "creature[%d:%d:%d] is create in position[%f,%f,%f]", creature->get_id( ), creator.creator_id( ), creator.tpl_id( ), creature->position( ).x( ), creature->position( ).y( ), creature->position( ).z( ) );
	OnCreatureBorn( *creature );

	UpdateDynamicBlock(*creature, 1);

	//给怪物添加初始buff;
	for( int32_t i = 0; i < tpl->buff_list_size( ); ++i )
	{
		const PBCreatureBornBuff& buff = tpl->buff_list( i );
        if( buff.buff_id( ) == 0 )
        {
            continue;
        }
		CBuffModule::InsertBuff( *creature, *creature, buff.buff_id( ), buff.buff_level( ), buff.buff_time( )  );
	}	

	creature_born_event( *creature );

	return creature;
}
*/
bool CSceneInstance::DespawnCreatureEntity( OBJ_ID_TYPE creature_id )
{
// 	CCreature* creature = CMAPObjManager::GetInstance( ).GetObjectByID< CCreature >( creature_id );
// 	if( NULL == creature )
// 	{
// 		LOG_ERROR( "default", "creature is null : %d", creature_id );
// 		return false;
// 	}
// 	CAggroModule::OnCreatureDestory( *creature );
// 	BroadcastOutvision( *creature );
// 	RemoveEntityFromAOI( *creature );
// //	creatures_.erase( creature_id );
// 	UpdateDynamicBlock(*creature, -1);
// 	creature_destroy_list_.push_back( creature_id );
// 	//CMAPObjManager::GetInstance( ).DestoryObject( creature_id );	
//    	LOG_DEBUG( "default", "creature[%d:%d:%d] is destroy", creature_id, creature->creator_id( ), creature->tpl_id( ) );
 	return true;
}

bool CSceneInstance::DespawnCreatureByCreatorId( int32_t creator_id )
{
//     CCreature* creature = GetCreatureByCreatorId( creator_id );
//     if( NULL == creature )
//     {
//         return false;
//     }
//     return DespawnCreatureEntity( creature->get_id( ) );
	return false;
}

bool CSceneInstance::PlayerEnter( Player& player, const ::common::CVector3& position, float angle )
{
	//TODO 许亚军添加
	player.InitializePlayerSceneInfo(true);

 	player.set_position( position );	
    player.set_angle( angle );
 	player.set_instance_id( instance_id_ );

	AddEntityToAOI( player );
	BroadcastInvision( player, player.GetPlayerId( ) );//广播角色进入
	// 同步角色可视表

	NotifyVision( player );

	OnPlayerEnter( player );

	CMainScene* main_scene = CSceneManager::GetInstance().GetMainSceneByinstance(instance_id());
	if (main_scene != NULL) {
		main_scene->UpdateLinePlayerCount(line_id(), 1);
	}
	return true;
}

bool CSceneInstance::PlayerLeave( Player& player )
{
	BroadcastOutvision( player, player.GetPlayerId( ) );	
	RemoveEntityFromAOI( player );

	CMainScene* main_scene = CSceneManager::GetInstance().GetMainSceneByinstance(instance_id());
	if (main_scene != NULL) {
		main_scene->UpdateLinePlayerCount(line_id(), -1);
	}
	player.vision_link().Clear();
	return true;
}

bool CSceneInstance::CharacterEnter(Player& character, const ::common::CVector3& position )
{
// 	character.set_position( position );	
// 	character.set_instance_id( instance_id_ );
	AddEntityToAOI( character );
	BroadcastInvision( character );
	return true;
}

bool CSceneInstance::CharacterLeave(Player& character )
{
	BroadcastOutvision( character );	
	RemoveEntityFromAOI( character );
	//character.set_instance_id( 0 );
	return true;
}

void CSceneInstance::BroadcastViewData( Player& character, int32_t data_type )
{
// 	PBMsgS2CViewDataBroadcast msg;
// 	msg.set_entity_id( character.get_id( ) );
// 	if( data_type & EVIEW_DATA_CUR_HP )
// 	{
// 		PBViewData* data = msg.add_view_data( );
// 		if( NULL != data )
// 		{
// 			data->set_data_type( EVIEW_DATA_CUR_HP );
// 			data->set_data_value( character.GetFormulaCur( ).cur_hp( ) );
// 		}
// 	}
// 	if( data_type & EVIEW_DATA_MAX_HP )
// 	{
// 		PBViewData* data = msg.add_view_data( );
// 		if( NULL != data )
// 		{
// 			data->set_data_type( EVIEW_DATA_MAX_HP );
// 			data->set_data_value( character.GetMaxHP(character.GetAttFormula()) );
// 		}
// 	}
// 	if( data_type & EVIEW_DATA_CUR_LEVEL )
// 	{
// 		PBViewData* data = msg.add_view_data( );
// 		if( NULL != data )
// 		{
// 			data->set_data_type( EVIEW_DATA_CUR_LEVEL );
// 			data->set_data_value( character.level( ) );
// 		}
// 	}
// 	if( msg.view_data_size( ) > 0 )
// 	{
// 		BroadcastViewMessage( character, ID_SCENE_ENTITY_VIEW_DATA_BROADCAST, msg );
// 	}
}

void CSceneInstance::BroadcastInvision(CEntity& entity, int32_t exclude_role_id )
{
	Json::Value notify;
	notify["msgid"] = add_walk_object;
	
	Json::Value _arrayObj;
	Json::Value _info;
	_arrayObj.clear();
	entity.SerialToJson(_info);
	_arrayObj.append(_info);
	notify["al"] = _arrayObj;
	BroadcastViewMessage(entity, add_walk_object, notify, exclude_role_id);
}

void CSceneInstance::BroadcastOutvision(CEntity& entity, int32_t exclude_role_id )
{
	Json::Value notify;
	notify["msgid"] = delete_walk_object;
	Json::Value _arrayObj;
	Json::Value key = entity.GetKey();
	_arrayObj.append(key);

	notify["dl"] = _arrayObj;
	BroadcastViewMessage( entity, delete_walk_object, notify, exclude_role_id );
}

void CSceneInstance::BroadcastMountChange( Player& entity )
{
// 	PBMsgS2CEntityMountUpdate msg;
// 	msg.set_entity_id( entity.get_id( ) );
// 	msg.set_mount_id( entity.mount_id( ) );
// 	if ( entity.role_mount().task_mount_id() != 0 )
// 	{
// 		msg.set_task_mount_id(entity.role_mount().task_mount_id());
// 		msg.set_task_id(entity.role_mount().task_id());
// 	}
// 	BroadcastViewMessage( entity, ID_SCEEN_ENTITY_UPDATE_MOUNT, msg );
}

void CSceneInstance::BroadcastPosition(Player& entity, int32_t exclude_role_id, int32_t move_flag )
{
	Json::Value notify;
	notify["msgid"] = c_update_player_sync_info;

	uint32_t flag = 0;
	flag |= uint32_t(UpdatePlayerInfoType::Position);
	flag |= uint32_t(UpdatePlayerInfoType::Orientation);
	
	Json::Value jv;
	jv.clear();

	jv["fg"] = flag;

	jv["si"] = entity.GetSceneId();
	jv["ky"] = entity.GetKey();
	jv["px"] = entity.position().x();
	jv["pz"] = entity.position().z();
	jv["py"] = entity.position().y();


	jv["tp"] = 0;
	jv["ox"] = entity.orientation_x();
	jv["oz"] = entity.orientation_z();
	jv["oy"] = entity.orientation_y();

	notify["list"].append(jv);

	BroadcastViewMessage(entity, c_update_player_sync_info, notify, exclude_role_id);
}


void CSceneInstance::DumpPosition( )
{
	for( int32_t i = 0; i < cell_size_; ++i )
	{
		SceneCellPlayerLoop( i, continue, 
			{
				CEntity* entity = node->parent( );
				if( NULL != entity )
				{
					LOG_INFO( "default", "entity :%d in position[%f,%f,%f]", entity->get_id( ), entity->position( ).x( ), entity->position( ).y( ), entity->position( ).z( ) );
				}
			}
		);
	}	
	for (int32_t i = 0; i < cell_size_; ++i)
	{
		SceneCellEntityLoop(i, continue,
		{
			CEntity* entity = node->parent();
			if (NULL != entity)
			{
				LOG_INFO("default", "entity :%d in position[%f,%f,%f]", entity->get_id(), entity->position().x(), entity->position().y(), entity->position().z());
			}
		}
		);
	}
}

int32_t CSceneInstance::NotifyVision( Player& player )
{
	int32_t notify_num = 0;
	int32_t all_notify_num = 0;
	int32_t send_msg_num = 0;


	Json::Value notify;
	notify["msgid"] = add_walk_object;

	Json::Value _arrayObj;
	_arrayObj.clear();
	TTargetList near_entity_list;
	SelectEntity( player, near_entity_list, CNearSelector( player ) );
	for( TTargetList::iterator iter = near_entity_list.begin( ); iter != near_entity_list.end( ); ++iter )
	{
		CEntity* near_entity = *iter;
		if( NULL == near_entity )
		{
			continue;
		}
// 		if ( near_entity->GetEntityType() != OBJTYPE_PLAYER)
// 		{
// 			continue;
// 		}
// 		Player* near_player = dynamic_cast<Player*>(near_entity);
// 		if (near_player == NULL )
// 		{
// 			continue;
// 		}

		int32_t rtn = SceneAddVision( player, *near_entity );
		if( rtn != common::SUCCEED && near_entity->GetEntityType()== OBJTYPE_PLAYER ) continue;

		Json::Value _info;
		near_entity->SerialToJson(_info);
		_arrayObj.append(_info);


		notify_num++;
		all_notify_num++;
		if( notify_num > 50 )
		{
			send_msg_num++;
			notify["al"] = _arrayObj;
			std::string sendstr = JsonWriter(notify);
			player.SendToClient(&sendstr, add_walk_object);
			notify_num = 0;
			notify.clear( );
			_arrayObj.clear();
		}
	}

	if(_arrayObj.size() > 0 )
	{
		send_msg_num++;
		notify["al"] = _arrayObj;
		std::string sendstr = JsonWriter(notify);
		player.SendToClient(&sendstr, add_walk_object);
	}

	LOG_INFO( "default", "player %d %d notify scene %d invision notify_all %d", player.GetAccount( ), player.GetPlayerId( ),
		tpl_id( ), all_notify_num );

 	return common::SUCCEED;
}

int32_t CSceneInstance::RevivePlayer( Player& player, int32_t revive_type )
{
// 	if( player.character_state( ) != ENTITY_STATE_DEATH )
// 	{
// 		return ::common::ESCENE_REVIVE_NOT_DIE;
// 	}	
// 	if( revive_type < 0 || revive_type >= REVIVE_TYPE_COUNT )
// 	{
// 		//不支持这种复活类型;
// 		return ::common::ESCENE_REVIVE_MAX_COUNT;
// 	}
// 	SSceneRoleData* scene_role_data = GetSceneRoleData( player.GetRoleID( ) );
// 	if( NULL == scene_role_data )
// 	{
// 		return ::common::ESCENE_REVIVE_DATA_NULL;
// 	}
// 	//如果本场景这种复活次数有限制;
// 	const CSceneTpl* tpl = CTPLManager::GetInstance( ).GetSceneTpl( tpl_id_ );
// 	if( NULL == tpl )	
// 	{
// 		return ::common::ESCENE_REVIVE_TPL_NULL;
// 	}
// 	int32_t max_revive = GetMaxRevive( revive_type );
// 	int32_t cur_revive = scene_role_data->GetReviveTimes( revive_type );
// 	if( max_revive != -1 &&
// 		cur_revive >= max_revive )
// 	{
// 		//已经到达复活次数上限;
// 		return ::common::ESCENE_REVIVE_MAX_COUNT;
// 	}
// 	switch( revive_type )
// 	{
// 		case REVIVE_TYPE_YUANDI:
// 			{
// 				//原地复活有消耗;
// 				CConsumeList consume_list;
// 				if( GetReviveConsume( revive_type, cur_revive + 1, consume_list ) == false )
// 				{
// 					return ::common::ESCENE_REVIVE_CONSUME_FAIL;
// 				}
// 				if( CConsumeModule::CheckConsume( player, consume_list ) != 0 )
// 				{
// 					return ::common::ESCENE_REVIVE_CONSUME_NOT_ENOUGH;	
// 				}
// 				LOG_EVENT( player, EACTIVE_REVIVE, 0, 0, 0 );	
// 				if( CConsumeModule::ConsumeReduce( player, consume_list ) != 0 )
// 				{
// 					return ::common::ESCENE_REVIVE_CONSUME_FAIL;
// 				}	
// 
// 				//const TPropsListVector& props_list= ;
// 				const CDropList::TPropsListVector& props_list = consume_list.GetPropsList();
// 				//const CConsumeList::TPropsListVector& props_list = consume_list.GetPropsList( );
// 				for (CDropList::TPropsListVector::const_iterator it = props_list.begin( ) ; it != props_list.end( ); ++it )
// 				{
// 					const CPropsInfo& props_item = *it;
// 					//原地复活消耗币之后需要给予玩家提示“本次原地复活消耗{0}个{1}”
// 					CMsgCode::SendMsgCodeToPlayer(player, ::common::ESCENE_REVIVE_CONSUME_NUM_NOTICE, props_item.props_num(), props_item.props_id());
// 				}
// 
// 				player.GetRolePack( ).PackFlush( player );
// 				player.GetFormulaCur( ).set_cur_hp( player.GetMaxHP(player.GetAttFormula()) );
// 				player.UpdateCharacterState( ENTITY_STATE_NORMAL );		
// 				//广播复活消息;
// 				PBMsgS2CReviveBroadcast revive_broadcast;
// 				revive_broadcast.set_entity_id( player.get_id( ) );
// 				BroadcastViewMessage( player, ID_SCENE_REVIVE_BROADCAST, revive_broadcast );
// 				//广播属性变化;
// 				BroadcastViewData( player, EVIEW_DATA_CUR_HP );
// 			}
// 			break;	
// 		case REVIVE_TYPE_CHUSHENGDIAN:
// 			{
// 				if( CUR_MS < player.die_time( ) + GetReviveCD( REVIVE_TYPE_CHUSHENGDIAN ) )
// 				{
// 					return ::common::ESCENE_REVIVE_CD;	
// 				}
// 				player.UpdateCharacterState( ENTITY_STATE_NORMAL );		
// 				//广播复活消息;
// 				PBMsgS2CReviveBroadcast revive_broadcast;
// 				revive_broadcast.set_entity_id( player.get_id( ) );
// 				BroadcastViewMessage( player, ID_SCENE_REVIVE_BROADCAST, revive_broadcast );
//                 float rate = tpl->revive_hp_rate( ) > 0 ? tpl->revive_hp_rate( ) : revive_hp_rate.value( );
// 
// 				player.GetFormulaCur( ).set_cur_hp( rate * player.GetMaxHP( player.GetAttFormula() ) );
// 				BroadcastViewData( player, EVIEW_DATA_CUR_HP );
// 
// 				//传送到出生点;
// 				const CSceneTpl* tpl = CTPLManager::GetInstance( ).GetSceneTpl( tpl_id_ );
// 				if( NULL == tpl )	
// 				{
// 					return ::common::ESCENE_REVIVE_SCENE_TPL_NULL;
// 				}
// 				const CSpawnArea& spawn_area = tpl->spawn_area( );
// 				::common::CVector3 position;
// 				float angle = 0;
// 				if( spawn_area.GetRandomPosition( position, angle ) == false )
// 				{
// 					return ::common::ESCENE_REVIVE_NO_SPAWN_AREA;
// 				}
// 				CSceneScript& scene_script = CSceneManager::GetInstance( ).GetSceneScript( script_ );
// 				scene_script.FixSpawnPosition( *this, player, position, angle);
// 				CSceneManager::GetInstance( ).Teleport( player, player.instance_id( ), position, angle );
// 			}
// 			break;
// 		case REVIVE_TYPE_HUICHENG:
// 			{
// 				//传送出副本;
// 				CSceneManager::GetInstance( ).LeaveDungeon( player );
// 			}
// 			break;
// 		default:
// 			return ::common::ESCENE_REVIVE_NOT_SUPPORT;
// 	}
// 	scene_role_data->SetReviveTimes( revive_type, cur_revive + 1 );
// 	CSceneScript& scene_script = CSceneManager::GetInstance( ).GetSceneScript( script_ );
// 	scene_script.OnRoleRevive( *this, player );
// 	return ::common::SUCCESS;
	return 0;
}

void CSceneInstance::StopAI( )
{
	/*
    TCreatureSet creatures = creatures_;//拷贝;
    for( TCreatureSet::iterator iter = creatures.begin( ); iter != creatures.end( ); ++iter )
    {
		OBJ_ID_TYPE obj_id = *iter;
        CCreature* creature = CMAPObjManager::GetInstance( ).GetObjectByID< CCreature >( obj_id );
        if( NULL == creature )
        {
            continue; 
        }
        const PBCreatureTpl* creature_tpl = CTPLManager::GetInstance( ).GetCreatureTpl( creature->tpl_id( ) );  
        if( NULL == creature_tpl )
        {
            continue;
        }
        if( creature_tpl->creature_type( ) == CREATURE_TYPE_MONSTER )
        {
            DespawnCreatureEntity( obj_id );
        } 
    }
	//需要关闭所有的触发器;
	for( TTriggerVector::iterator iter = triggers_.begin( ); iter != triggers_.end( ); ++iter )
	{
		iter->set_active( false );	
	}
	*/
}

void CSceneInstance::TickUpdate( )
{
	if( update_sec_ != CUR_SEC )
	{
		update_sec_ = CUR_SEC;
	}

	// tick up 
	int32_t frame = CUR_FRAME;
	int32_t last_frame = last_logic_frame_;
	if( frame >= ( last_frame + 5 )  )
	{
		{
			// logic tick

			for( TCreatureSet::iterator it = creatures_.begin (); it != creatures_.end (); ++it )
			{
				Monster* creature = CMAPObjManager::GetInstance ().GetObjectByID< Monster > ( *it );
				if( NULL == creature )
				{
					continue;
				}
				creature->TickUpdate ();
			}
		}

		last_logic_frame_ = frame;
	}
	else if( frame < last_frame )
	{
		last_logic_frame_ = frame;
	}


// 	for( TDespawnCreatureList::iterator iter = creature_destroy_list_.begin( ); iter != creature_destroy_list_.end( ); ++iter )
// 	{
// 		OBJ_ID_TYPE creature_obj_id = *iter;
// 		CMAPObjManager::GetInstance( ).DestoryObject( creature_obj_id );
// 
// 		TCreatureSet::iterator iter = creatures_.find( creature_obj_id );
// 		if( iter != creatures_.end( ) )
// 		{
// 			creatures_.erase( iter );
// 		}
// 	}
// 	creature_destroy_list_.clear( );
}

void CSceneInstance::Dump( )
{
	int32_t player_num = 0;// role_data_map_.size();
	int32_t creature_num = creatures_.size( );
	int32_t common_creature = common_creatures_.size( );
	LOG_INFO( "stat", "  %-18d  %-10d  %-10d  %-10d  %-10d  %-10d", tpl_id( ), line_id( ), instance_id( ), player_num, 
		creature_num, common_creature );
}

int32_t CSceneInstance::TeleportToBornPoint( Player& player )
{
//     const CSceneTpl* tpl = CTPLManager::GetInstance( ).GetSceneTpl( tpl_id_ );
//     if( NULL == tpl )	
//     {
//         return ::common::ESCENE_REVIVE_SCENE_TPL_NULL;
//     }
//     const CSpawnArea& spawn_area = tpl->spawn_area( );
//     ::common::CVector3 position;
//     float angle = 0;
//     if( spawn_area.GetRandomPosition( position, angle ) == false )
//     {
//         return ::common::ESCENE_REVIVE_NO_SPAWN_AREA;
//     }
//     CSceneScript& scene_script = CSceneManager::GetInstance( ).GetSceneScript( script_ );
//     scene_script.FixSpawnPosition( *this, player, position, angle);
//     CSceneManager::GetInstance( ).Teleport( player, player.instance_id( ), position, angle );
//     return ::common::SUCCESS;
	return 0;
}

int32_t CSceneInstance::SceneAddVision( CEntity& first, CEntity& second )
{
// 	if (vision_limit_ == 0) return common::SUCCESS;
// 	if (player_vision_limit.value() <= 0) return common::SUCCESS;
// 	if (second.GetEntityType() == OBJTYPE_CREATURE) return common::SUCCESS;
// 
// 	if (first.GetEntityType() == OBJTYPE_PLAYER)
// 	{
// 		CPlayer& player = (CPlayer&)first;
// 
// 		CPlayerVision& player_vision = player.player_vision();
// 		int32_t rtn = player_vision.AddVision(player, second);
// 		LOG_DEBUG("default", "player %d %d entity %d, vision num %d rtn %d", player.GetAccountID(),
// 			player.GetRoleID(), second.get_id(), player_vision.vision_num(), rtn);
// 		return rtn;
// 	}
// 
// 	return common::ESCENE_VISION_FULL;
	uint32_t ret_code = ::common::SUCCEED;
	if (first.GetEntityType() == OBJTYPE_PLAYER && second.GetEntityType() == OBJTYPE_PLAYER)
	{
		Player* firstptr = dynamic_cast<Player*>(&first);
		if (firstptr == nullptr) {
			return -1;
		}
		Player* secondptr = dynamic_cast<Player*>(&second);
		if (secondptr == nullptr) {
			return -1;
		}
		ret_code = firstptr->vision_link().AddBroadList(secondptr);
	}
	return ret_code;
}

int32_t CSceneInstance::SceneRemoveVision( CEntity& first, CEntity& second )
{
// 	if( vision_limit_ == 0 ) return common::SUCCESS;
// 	if( player_vision_limit.value( ) <= 0 ) return common::SUCCESS;
// 	if( second.GetEntityType( ) == OBJTYPE_CREATURE ) return common::SUCCESS;
// 
// 	if( first.GetEntityType( ) == OBJTYPE_PLAYER )
// 	{
// 		CPlayer& player = ( CPlayer& )first;
// 
// 		CPlayerVision& player_vision = player.player_vision( );
// 		int32_t rtn = player_vision.RemoveVision( second );
// 
// 		LOG_DEBUG( "default", "player %d %d entity %d , vision num %d rtn %d", player.GetAccountID( ), 
// 			player.GetRoleID( ), second.get_id( ), player_vision.vision_num( ), rtn );
// 			
// 		return rtn;
// 	}

	if (first.GetEntityType() == OBJTYPE_PLAYER && second.GetEntityType() == OBJTYPE_PLAYER)
	{
		Player* firstptr = dynamic_cast<Player*>(&first);
		if (firstptr == nullptr) {
			return -1;
		}
		Player* secondptr = dynamic_cast<Player*>(&second);
		if (secondptr == nullptr) {
			return -1;
		}
		firstptr->vision_link().RemoveBroadList(secondptr);
	}
	return common::SUCCEED;
}

int32_t CSceneInstance::SceneSendMsg( Player& watcher, CEntity& entity, int32_t msg_id, Json::Value& msg )
{
	if( vision_limit_ == 0 ) return common::SUCCEED;
	int32_t rtn = SceneInVision( watcher, entity, msg_id, msg );
	if( rtn != common::SUCCEED) return rtn;

	if( watcher.get_id( ) == entity.get_id( ) ) return common::SUCCEED;
	
	//rtn = watcher.player_vision( ).AddBroadcastMsgNum( msg_id );
	if( rtn != common::SUCCEED)
	{
		LOG_DEBUG( "default", "player %d %d recv broadcast msg %d busy", watcher.GetAccount( ), watcher.GetPlayerId( ), msg_id );
		return rtn;
	}

	return rtn;
}

int32_t CSceneInstance::SceneInVision( Player& watcher, CEntity& entity, int32_t msg_id, Json::Value& msg )
{
	if( vision_limit_ == 0 ) return common::SUCCEED;
//	if( entity.GetEntityType( ) == OBJTYPE_CREATURE ) return common::SUCCEED;
// 	if( player_vision_limit.value( ) <= 0 ) return common::SUCCEED;
// 	if( watcher.get_id( ) == entity.get_id( ) ) return common::SUCCEED;
// 
// 	CPlayerVision::EVisionLevel vision_lvl = watcher.player_vision( ).VisionLvl( entity );
// 
// 	// ＮＰＣ和可视级别Lvl1 消息都广播	
// 	if( vision_lvl == CPlayerVision::EVisionLvl1 || vision_lvl == CPlayerVision::EVisionCreature ) return common::SUCCEED;
// 	// 不在可视表，　消息不广播
// 	if( vision_lvl == CPlayerVision::EVisionNone )
// 	{ 
// 		LOG_DEBUG( "default", "player %d %d entity %d not in vision", watcher.GetAccountID( ), watcher.GetRoleID( ), entity.get_id( ) );
// 		return common::ESCENE_ISNOT_IN_VISION;
// 	}

	return common::SUCCEED;
}

void CSceneInstance::SendMsg2Broadcast(uint32_t msg_id, Json::Value& msg, T_BROADCAST_PLAYER_TYPE& broad_cast)
{
	std::string msgstr = JsonWriter(msg);
	T_BROADCAST_PLAYER_TYPE::iterator it = broad_cast.begin();
	for (; it != broad_cast.end(); ++it )
	{
		Player* player = *it;
		if ( player == NULL )
		{
			continue;
		}
		player->SendToClient(&msgstr, msg_id);
	}
}

SSceneRoleData* CSceneInstance::GetSceneRoleData(int32_t role_id)
{
	TSceneRoleDataMap::iterator iter = role_data_map_.find(role_id);
	if (iter == role_data_map_.end())
	{
		return NULL;
	}
	else
	{
		return &(iter->second);
	}
}

void CSceneInstance::BroadcastHp(CEntity& entity, int32_t exclude_role_id)
{
	Json::Value notify;
	notify["msgid"] = c_update_map_element_info;

	uint32_t flag = 0;
	flag |= uint32_t(UpdateMapElementInfoType::Hp);

	notify["fg"] = flag;

	if ( entity.GetEntityType() != OBJTYPE_CREATURE )
	{
		return;
	}
	int32_t _gt = int32_t(entity.GetClientType());
	Monster& monster = dynamic_cast<Monster&>(entity);

	notify["si"] = monster.GetSceneId();
	notify["ky"] = monster.GetKey();
	notify["hp"] = monster.GetHp();
	notify["ox"] = monster.GetOrientationX();
	notify["oy"] = monster.GetOrientationY();
	notify["oz"] = monster.GetOrientationX();
	notify["rc"] = monster.GetResetCount();
	notify["tp"] = _gt;
	notify["nm"] = "monster";

	BroadcastViewMessage(entity, c_update_map_element_info, notify, exclude_role_id);
}

void CSceneInstance::BroadcastMonsterPosition(CEntity& entity, int32_t exclude_role_id, int32_t move_flag)
{
	Json::Value notify;
	notify["msgid"] = c_update_map_element_info;

	uint32_t flag = 0;
	flag |= uint32_t(UpdateMapElementInfoType::Position);

	notify["fg"] = flag;

	int32_t _gt = int32_t(entity.GetClientType());
	if (_gt > GOT_PLAYER)
	{
		_gt -= GOT_PLAYER;
	}
	notify["tp"] = _gt;

	notify["si"] = entity.GetSceneId();
	notify["ky"] = entity.GetKey();
	notify["px"] = entity.position().x();
	notify["pz"] = entity.position().z();
	notify["py"] = entity.position().y();

	BroadcastViewMessage(entity, c_update_map_element_info, notify, exclude_role_id);
}

void CSceneInstance::BroadcastPlayerHp(CEntity& entity, int32_t exclude_role_id)
{
	Json::Value notify;
	notify["msgid"] = c_update_player_sync_info;

	uint32_t flag = 0;
	flag |= uint32_t(UpdatePlayerInfoType::Hp);

	Json::Value jv;
	jv.clear();

	jv["fg"] = flag;

	jv["hp"] = entity.GetFightPro().GetHp();

	notify["list"].append(jv);

	BroadcastViewMessage(entity, c_update_player_sync_info, notify, exclude_role_id);
	
}

CEntity* CSceneInstance::GetCreaturesEnityByKey(uint32_t key)
{
	auto it_key = creatures_key_id.find(key);

	if (it_key == creatures_key_id.end()) {
		return NULL;
	}

	TCreatureSet::iterator iter = creatures_.find(it_key->second);
	if (iter == creatures_.end())
	{
		return NULL;
	}
	return  CMAPObjManager::GetInstance().GetObjectByID<CEntity>(*iter);
}

void CSceneInstance::Broadcast(Player & player, uint32_t flag, uint32_t exclude_role_id)
{

	Json::Value m_msg_json;
	Json::Value msg_json_broad;
	uint32_t flag_broadcast = 0;

	if ((flag & uint32_t(UpdatePlayerInfoType::Hp)) > 0)
	{
		msg_json_broad["si"] = player.GetSceneId();
		msg_json_broad["ky"] = player.GetKey();
		msg_json_broad["hp"] = player.GetPlayerHp();
		flag_broadcast |= (uint32_t)UpdatePlayerInfoType::Hp;
	}

	if ((flag & uint32_t(UpdatePlayerInfoType::Orientation)) > 0)
	{
		msg_json_broad["ox"] = player.GetOrientationX();
		msg_json_broad["oz"] = player.GetOrientationZ();
		msg_json_broad["oy"] = player.GetOrientationY();

		int32_t _gt = int32_t(player.GetObjectType());
		if (_gt > GOT_PLAYER)
		{
			_gt -= GOT_PLAYER;
		}
		msg_json_broad["tp"] = _gt;
		flag_broadcast |= (uint32_t)UpdatePlayerInfoType::Orientation;
	}
	if (flag_broadcast > 0)
	{
		msg_json_broad["fg"] = flag_broadcast;

		m_msg_json["msgid"] = c_update_player_sync_info;
		m_msg_json["list"].append(msg_json_broad);
		CSceneInstance* ins = CSceneManager::GetInstance().GetSceneInstance(player.instance_id());
		if (ins == NULL) {
			return;
		}
		ins->BroadcastViewMessage(player, c_update_player_sync_info, m_msg_json, exclude_role_id);
	}

	// 清除更新状态
	// player.ClearUpdateInfoMyFlag();
}